package com.ycy.lucene.index;

import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.apache.lucene.store.FSDirectory;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

@Slf4j
public class IndexReadDemo {

    static volatile IndexSearcher indexSearcher = null;

    public static IndexSearcher getIndexSearch() {
        if (indexSearcher == null)
            synchronized (IndexReadDemo.class) {
                if (indexSearcher == null) {
                    DirectoryReader indexReader = null;
                    try {
                        indexReader = DirectoryReader.open(FSDirectory.open(Paths.get(IndexCreateDemo.indexpath)));
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    indexSearcher = new IndexSearcher(indexReader);
                }
            }
        return indexSearcher;
    }

    public static void refreshIndexSearch() {
        synchronized (IndexReadDemo.class) {
            if (indexSearcher != null) {
                DirectoryReader indexReader = (DirectoryReader) indexSearcher.getIndexReader();
                DirectoryReader newReader = null;
                try {
                    // 重要:如果索引发生更新和删除,必须重新生成IndexSearch才能查询到文更新和删除后的文档变化。
                    newReader = DirectoryReader.openIfChanged(indexReader);

                    if (newReader != null) {
                        indexReader.close();
                        IndexSearcher searcher = new IndexSearcher(newReader);
                        indexSearcher = searcher;
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static String search() {
        //查询第一个文档
        TermQuery termQuery = new TermQuery(new Term("id", "22130906"));
        StringBuilder stringBuilder = new StringBuilder();
        TopDocs topDocs = null;
        try {
            IndexSearcher indexSearch = getIndexSearch();
            topDocs = indexSearch.search(termQuery, 10);
            if (topDocs == null || topDocs.scoreDocs == null) {
                return stringBuilder.toString();
            }
            for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
                Document doc = indexSearch.doc(scoreDoc.doc);
                stringBuilder.append("id:"+doc.get("id") + "," +"name:" +doc.get("name"));
                stringBuilder.append("\\n");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return stringBuilder.toString();
    }

  public static void search(Query query, int docCount, Sort sort) {
    IndexReader indexReader = null;
    try {
      Path path = Paths.get(IndexCreateDemo.indexpath);
      indexReader = DirectoryReader.open(FSDirectory.open(path));
      IndexSearcher isearch = new IndexSearcher(indexReader);
      TopDocs topDocs = null;
      log.info("query -> {}",query);
      if (sort == null) {
        topDocs = isearch.search(query, docCount);
      } else {
        topDocs = isearch.search(query, docCount, sort);
      }
      for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
        Document doc = isearch.doc(scoreDoc.doc);
        String res = String.format(" scoreDoc : %s, docid : %s, id : %s, name : %s, opendate : %s, sales : %s, group : %s, has : %s, address : %s",
                scoreDoc.score, scoreDoc.doc,
                doc.get("id"), doc.get("name"), doc.get("opendate"), doc.get("sales"), doc.get("group"), doc.get("has"), doc.get("address"));
        log.info("res -> {}", res);
        //explain 可以对文档的打分做解释
        Explanation explain = isearch.explain(query, scoreDoc.doc);
        log.info("explain -> {}",explain.toString());
      }
      System.out.println("共检索出 " + topDocs.totalHits + " 条记录");
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        indexReader.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

  }


  public static void search(Query query) {
    search(query, 100, null);
  }

}
